package com.leyou.order.service;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.leyou.common.auth.pojo.UserHolder;
import com.leyou.common.constant.LyConstant;
import com.leyou.common.dto.PageResult;
import com.leyou.common.exception.pojo.ExceptionEnum;
import com.leyou.common.exception.pojo.LyException;
import com.leyou.common.utils.BeanHelper;
import com.leyou.common.utils.IdWorker;
import com.leyou.item.client.ItemClient;
import com.leyou.item.dto.SpuDTO;
import com.leyou.item.entity.Sku;
import com.leyou.order.dto.CartDTO;
import com.leyou.order.dto.OrderDTO;
import com.leyou.order.dto.OrderStatusEnum;
import com.leyou.order.dto.OrderVO;
import com.leyou.order.entity.Order;
import com.leyou.order.entity.OrderDetail;
import com.leyou.order.entity.OrderLogistics;
import com.leyou.order.mapper.OrderDetailMapper;
import com.leyou.order.mapper.OrderLogisticsMapper;
import com.leyou.order.mapper.OrderMapper;
import com.leyou.order.utils.PayHelper;
import com.leyou.user.client.UserClient;
import com.leyou.user.dto.AddressDTO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import tk.mybatis.mapper.entity.Example;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Slf4j
@Service
@Transactional
public class OrderService {

    @Autowired
    private OrderMapper orderMapper;

    @Autowired
    private OrderDetailMapper detailMapper;

    @Autowired
    private OrderLogisticsMapper logisticsMapper;

    @Autowired
    private UserClient userClient;

    @Autowired
    private ItemClient itemClient;

    @Autowired
    private IdWorker idWorker;

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private PayHelper payHelper;

    public Long saveOrder(OrderDTO orderDTO) {
        //获取订单id
        Long orderId = idWorker.nextId();
        //创建订单
        Order order = new Order();
        order.setOrderId(orderId);
        order.setStatus(OrderStatusEnum.INIT.value());
        order.setUserId(UserHolder.getUserId());
        order.setPaymentType(1);
        order.setInvoiceType(0);
        order.setPostFee(0L);//邮费包邮

        //得到购买的购物车信息
        List<CartDTO> carts = orderDTO.getCarts();
        //把list结构的购物车对象变成map
        Map<Long, Integer> cartsMap = carts.stream().collect(Collectors.toMap(CartDTO::getSkuId, CartDTO::getNum));
        //通过购物车信息得到skuId的集合
        List<Long> skuIds = carts.stream().map(CartDTO::getSkuId).collect(Collectors.toList());
        //得到所有的sku对象
        List<Sku> skus = itemClient.findSkusByIds(skuIds);
        //遍历skus的集合并计算出总金额 计算方式是 每个sku的价格乘以购买数量，最终一起相加
        long totalFee = skus.stream().mapToLong(sku -> sku.getPrice() * cartsMap.get(sku.getId())).sum();
        order.setTotalFee(totalFee);//总金额，所有sku金额相加
        order.setActualFee(1L);//实际付款金额 写一分钱，便于测试
        //保存订单
        orderMapper.insertSelective(order);

        //定义一个订单详情列表对象
        List<OrderDetail> detailList = new ArrayList<>();
        //遍历sku对象的集合
        skus.forEach(sku -> {
            OrderDetail orderDetail = new OrderDetail();
            orderDetail.setId(idWorker.nextId());
            orderDetail.setOrderId(orderId);
            orderDetail.setImage(StringUtils.substringBefore(sku.getImages(), ","));
            orderDetail.setOwnSpec(sku.getOwnSpec());
            orderDetail.setPrice(sku.getPrice());
            orderDetail.setTitle(sku.getTitle());
            orderDetail.setSkuId(sku.getId());
            orderDetail.setNum(cartsMap.get(sku.getId()));
            orderDetail.setCreateTime(new Date());
            orderDetail.setUpdateTime(new Date());
            detailList.add(orderDetail);
        });
        //保存订单详情
        detailMapper.insertList(detailList);

        //查询用户物流信息
        AddressDTO addressDTO = userClient.queryAddressById(UserHolder.getUserId(), orderDTO.getAddressId());
        //把dto对象转成entity对象
        OrderLogistics orderLogistics = BeanHelper.copyProperties(addressDTO, OrderLogistics.class);
        orderLogistics.setOrderId(orderId);
        //保存订单物流数据
        logisticsMapper.insertSelective(orderLogistics);

        //减库存 一定要加到最后
        itemClient.minusStock(cartsMap);
        return orderId;
    }

    public OrderVO findOrderVoById(Long id) {
        //根据订单id查询订单对象
        Order order = orderMapper.selectByPrimaryKey(id);
        if(order==null){
            throw new LyException(ExceptionEnum.ORDER_NOT_FOUND);
        }
        //将entity转成vo
        OrderVO orderVO = BeanHelper.copyProperties(order, OrderVO.class);
        //查询订单详情列表
        OrderDetail record = new OrderDetail();
        record.setOrderId(id);
        List<OrderDetail> orderDetails = detailMapper.select(record);
        if(CollectionUtils.isEmpty(orderDetails)){
            throw new LyException(ExceptionEnum.ORDER_NOT_FOUND);
        }
        //给OrderVO中的订单详情赋值
        orderVO.setDetailList(orderDetails);
        //查询物流信息
        OrderLogistics orderLogistics = logisticsMapper.selectByPrimaryKey(id);
        if(orderLogistics==null){
            throw new LyException(ExceptionEnum.ORDER_NOT_FOUND);
        }
        orderVO.setLogistics(orderLogistics);
        return orderVO;
    }

    public String getPayUrl(Long id) {
        //获取支付链接在redis中的key
        String key = LyConstant.PAY_URL_PER+id;
        //查看当前订单的支付链接是否在redis中
        if(redisTemplate.hasKey(key)){
            //取出支付链接并返回
            return redisTemplate.opsForValue().get(key);
        }
        //根据订单号查询订单
        Order order = orderMapper.selectByPrimaryKey(id);
        //判断订单状态
        if(order.getStatus()!=OrderStatusEnum.INIT.value()){
            throw new LyException(501, "订单已支付，请不要重复支付！");
        }
        //调用工具类获取支付链接
        String payUrl = payHelper.getPayUrl(id, order.getActualFee());
        //将支付链接放入到redis中，有效时间为2小时
        redisTemplate.opsForValue().set(key, payUrl, 2, TimeUnit.HOURS);
        return payUrl;
    }

    public Integer getPayCode(Long id) {
        //根据订单号查询订单
        Order order = orderMapper.selectByPrimaryKey(id);
        if(order==null){
            throw new LyException(ExceptionEnum.ORDER_NOT_FOUND);
        }
        return order.getStatus();
    }

    public void checkWxNotify(Map<String, String> paramMap) {
        log.info("【微信来通知我们了！】业务开始了！！！！！！！！！！！");
        //校验通信标识和业务标识
        payHelper.checkPayResp(paramMap);
        //获取商品订单号
        Long outTradeNo = Long.valueOf(paramMap.get("out_trade_no"));
        //获取用户支付订单金额
        Long totalFee = Long.valueOf(paramMap.get("total_fee"));
        //根据商户订单号查询订单
        Order order = orderMapper.selectByPrimaryKey(outTradeNo);
        if(order==null){
            log.error("【微信来通知我们了！】订单不存在！");
            throw new LyException(ExceptionEnum.ORDER_NOT_FOUND);
        }
        //获取到订单金额
        Long actualFee = order.getActualFee();
        //判断订单金额与用户支付的金额是否一致
        if(!actualFee.equals(totalFee)){
            log.error("【微信来通知我们了！】支付金额有误！");
            throw new LyException(501, "支付金额有误！");
        }
        //修改订单状态
        Order record = new Order();
        record.setOrderId(outTradeNo);
        record.setStatus(OrderStatusEnum.PAY_UP.value());
        int count = orderMapper.updateByPrimaryKeySelective(record);
        if(count!=1){
            //注意：这里不抛异常，如果抛异常，我们会认为微信支付出错了，其实只是我们修改操作错了而已。回头人工处理。
            log.error("【微信来通知我们了！】修改订单状态有误！");
        }
        log.info("【微信来通知我们了！】业务结束了！！！！！！！！！！！");
    }

    //根据订单状态查OrderVo集合分页
    public PageResult<OrderVO> queryOrderPageByStatus(Integer page,Integer rows,String key,Integer status) {
        PageHelper.startPage(page,rows);
//        Order record = new Order();
//        record.setStatus(status);
////        record.setUserId(UserHolder.getUserId());
//        record.setUserId(32l);//测试用
//        List<Order> orderList = orderMapper.select(record);
        Example orderExample = new Example(Order.class);
        Example.Criteria orderCriteria = orderExample.createCriteria();
        if (status!=null){
            orderCriteria.andEqualTo("status",status);
        }
        orderCriteria.andEqualTo("userId",UserHolder.getUserId());
//        orderCriteria.andEqualTo("userId",32L);//测试用
        //按创建时间排序
        orderExample.setOrderByClause("create_time desc");
        List<Order> orderList = orderMapper.selectByExample(orderExample);
        if (CollectionUtils.isEmpty(orderList)){
            throw new LyException(ExceptionEnum.ORDER_NOT_FOUND);
        }
        List<OrderVO> orderVOList = BeanHelper.copyWithCollection(orderList, OrderVO.class);
        Example example = new Example(OrderDetail.class);
        Example.Criteria criteria = example.createCriteria();
        //判断是否有查询条件
        if(StringUtils.isNotBlank(key)){
            criteria.andLike("title", "%"+key+"%");
        }
        //查询所有订单详情
        List<OrderDetail> orderDetailList = detailMapper.selectByExample(example);
        //根据订单id分组
        Map<Long, List<OrderDetail>> detailsMap =
                orderDetailList.stream().collect(Collectors.groupingBy(OrderDetail::getOrderId));
        //查询所有
        List<OrderLogistics> logisticsList = logisticsMapper.selectAll();

        orderVOList.forEach(orderVO -> {
            orderVO.setDetailList(detailsMap.get(orderVO.getOrderId()));
            //若物流信息的订单id与orderVo的订单id相等则赋值
            logisticsList.forEach(orderLogistics -> {
                if (orderLogistics.getOrderId().equals(orderVO.getOrderId())){
                    orderVO.setLogistics(orderLogistics);
                }
            });
        });
        //       orderVOList.forEach(orderVO -> {
//            OrderDetail recordDetail = new OrderDetail();
//            record.setOrderId(orderVO.getOrderId());
//            List<OrderDetail> orderDetails = detailMapper.select(recordDetail);
//            if(CollectionUtils.isEmpty(orderDetails)){
//                throw new LyException(ExceptionEnum.ORDER_NOT_FOUND);
//            }
//            //给OrderVO中的订单详情赋值
//            orderVO.setDetailList(orderDetails);
//            //查询物流信息
//            OrderLogistics orderLogistics = logisticsMapper.selectByPrimaryKey(orderVO.getOrderId());
//            if(orderLogistics==null){
//                throw new LyException(ExceptionEnum.ORDER_NOT_FOUND);
//            }
//            orderVO.setLogistics(orderLogistics);
//        });
        PageInfo pageInfo = new PageInfo(orderList);
        //通过PageInfo封装一个自定义的分页对象PageResult
        PageResult<OrderVO> pageResult = new PageResult<>(pageInfo.getTotal(),
                pageInfo.getPages(),
                orderVOList);
        return pageResult;
    }
    /**
     * 根据订单状态查数量
     */
    public Integer queryOrderCountByStatus(Integer status) {
        Order record = new Order();
        record.setStatus(status);
        record.setUserId(UserHolder.getUserId());
//        record.setUserId(32l);//测试用
        Integer count = orderMapper.selectCount(record);
        if (count==0){
            throw new LyException(ExceptionEnum.ORDER_NOT_FOUND);
        }
        return count;
    }

    public void updateOrderStatusById(Long orderId) {
        try {
            Order order = orderMapper.selectByPrimaryKey(orderId);
            order.setStatus(6);
            orderMapper.updateByPrimaryKeySelective(order);
        } catch (Exception e) {
            throw new LyException(ExceptionEnum.UPDATE_OPERATION_FAIL);
        }
    }
}
